package com.awesome.common.base.mvvm

import android.view.LayoutInflater
import androidx.activity.ComponentActivity
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
import java.lang.Exception
import java.lang.reflect.ParameterizedType

/**
 * Author: JFangZ
 * Email: janezhang1901@163.com
 * Date: 2021/5/20 14:27
 * Description:获取ViewModel
 */
object ViewModelUtils {

    fun <T> getClass(t: Any): Class<T> {
        // 通过反射 获取父类泛型 (T) 对应 Class类
        return (t.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[0] as Class<T>
    }

    /**
     *
     */
    fun <VM : ViewModel> createViewModel(activity: ComponentActivity, position: Int): VM {
        val clazz = (activity.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[position] as Class<VM>
        return ViewModelProvider(activity).get(clazz)
    }


    fun <VM : ViewModel> createViewModel(fragment: Fragment, position: Int): VM {
        val clazz = (fragment.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[position] as Class<VM>
        return ViewModelProvider(fragment).get(clazz)
    }

    fun <VM : ViewModel> createActivityViewModel(fragment: Fragment, position: Int): VM {
        val clazz = (fragment.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[position] as Class<VM>
        return ViewModelProvider(fragment.requireActivity()).get(clazz)
    }


    fun <VB : ViewBinding> createViewBinding(activity: ComponentActivity, position: Int): VB? {
        try {
            val clazz = (activity.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[position] as Class<VB>
            val method = clazz.getMethod("inflate", LayoutInflater::class.java)
            return method.invoke(null, activity.layoutInflater) as VB

        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

    fun <VB : ViewBinding> createViewBinding(fragment: Fragment, position: Int): VB? {
        try {
            val clazz = (fragment.javaClass.genericSuperclass as ParameterizedType).actualTypeArguments[position] as Class<VB>
            val method = clazz.getDeclaredMethod("inflate", LayoutInflater::class.java)
            return method.invoke(null, fragment.layoutInflater) as VB
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return null
    }

}